import { Trie } from './Trie';
import { BaseRecycle, PoolManager } from '../../Manager/PoolManager';

export class TrieNode extends BaseRecycle {
  /** 节点字符串 */
  nodeValue: string;

  /** 父节点 */
  parent: TrieNode;

  /** 所属前缀树 */
  ownerTree: Trie;

  /** 节点深度(根节点为0) */
  depth: number;

  /** 是否是单词节点 */
  isTail: boolean;

  /** 是否是根节点 */
  isRoot: boolean;

  /** 子节点映射Map<节点字符串, 节点对象> */
  childNodesMap: Map<string, TrieNode>;

  /** 子节点数量 */
  childCount: number;

  /** 是否启用 */
  isActive: boolean = true;

  /**
   * 构造函数
   */
  constructor() {
    super();
    this.childNodesMap = new Map<string, TrieNode>();
  }

  /**
   * 重用节点
   * @param value - 节点字符串
   * @param parent - 父节点
   * @param ownerTree - 所属前缀树
   * @param depth - 节点深度
   * @param isTail - 是否是单词节点
   */
  reuse(value: string, parent: TrieNode, ownerTree: Trie, depth: number, isTail: boolean = false) {
    this.nodeValue = value;
    this.parent = parent;
    this.ownerTree = ownerTree;
    this.depth = depth;
    this.isTail = isTail;
    this.isActive = true;
  }

  /**
   * 释放节点
   */
  unuse() {
    this.nodeValue = null;
    this.parent = null;
    this.ownerTree = null;
    this.depth = 0;
    this.isTail = false;
    this.childNodesMap.clear();
    this.isActive = false;
    this.isRoot = false;
  }

  /**
   * 添加子节点
   * @param nodeWord - 子节点字符串
   * @param isTail - 是否是单词节点
   * @returns 添加的子节点
   */
  addChildNode(nodeWord: string, isTail: boolean): TrieNode {
    if (this.childNodesMap.has(nodeWord)) {
      // Debug.Log($"节点字符串:{NodeValue}已存在字符串:{nodeWord}的子节点,不重复添加子节点!");
      return this.childNodesMap.get(nodeWord);
    }
    const node = TrieNode.pop(nodeWord, this, this.ownerTree, this.depth + 1, isTail);
    this.childNodesMap.set(nodeWord, node);
    return node;
  }

  /**
   * 移除指定子节点
   * @param nodeWord - 子节点字符串
   * @returns 是否成功移除
   */
  removeChildNodeByWord(nodeWord: string): boolean {
    const childNode = this.getChildNode(nodeWord);
    return this.removeChildNode(childNode);
  }

  /**
   * 移除指定子节点
   * @param childNode - 子节点对象
   * @returns 是否成功移除
   */
  removeChildNode(childNode: TrieNode): boolean {
    if (childNode == null) {
      // Debug.LogError($"无法移除空节点!");
      return false;
    }
    const realChildNode = this.getChildNode(childNode.nodeValue);
    if (realChildNode != childNode) {
      // Debug.LogError($"移除的子节点单词:{childNode.NodeValue}对象不是同一个,移除子节点失败!");
      return false;
    }
    this.childNodesMap.delete(childNode.nodeValue);
    PoolManager.Ins().pushObj(childNode);
    return true;
  }

  /**
   * 当前节点从父节点移除
   * @returns 是否成功移除
   */
  removeFromParent(): boolean {
    if (this.isRoot) {
      // Debug.LogError($"当前节点是根节点，不允许从父节点移除，从父节点移除当前节点失败!");
      return false;
    }
    return this.parent.removeChildNode(this);
  }

  /**
   * 获取指定字符串的子节点
   * @param nodeWord - 子节点字符串
   * @returns 子节点对象
   */
  getChildNode(nodeWord: string): TrieNode {
    if (!this.childNodesMap.has(nodeWord)) {
      // Debug.Log($"节点字符串:{NodeValue}找不到子节点字符串:{nodeWord},获取子节点失败!");
      return null;
    }
    return this.childNodesMap.get(nodeWord);
  }

  /**
   * 是否包含指定字符串的子节点
   * @param nodeWord - 子节点字符串
   * @returns 是否包含
   */
  containWord(nodeWord: string): boolean {
    return this.childNodesMap.has(nodeWord);
  }

  /**
   * 获取当前节点构成的单词
   * 不管当前节点是否是单词节点,都返回从当前节点回溯到根节点拼接的单词
   * 若当前节点为根节点，则返回根节点的字符串(默认为"Root")
   * @returns 完整单词
   */
  getFullWord(): string {
    let trieNodeWord = this.nodeValue;
    let node = this.parent;
    while (node != null && !node.isRoot) {
      trieNodeWord = `${node.nodeValue}${Trie.separator}${trieNodeWord}`;
      node = node.parent;
    }
    return trieNodeWord;
  }
}
